feat: update Bob integration to skills-based layout for Bob 2.0#3415
feat: update Bob integration to skills-based layout for Bob 2.0#3415davidebibm wants to merge 28 commits into
Conversation
Bob 2.0 replaces the command-based workflow (.bob/commands/*.md) with a skills-based layout (.bob/skills/speckit-<name>/SKILL.md), matching the pattern used by Claude Code, Codex, and other skills-first agents. - Switch BobIntegration from MarkdownIntegration to SkillsIntegration - Update folder/dir from .bob/commands to .bob/skills - Change extension from .md to /SKILL.md (skills layout) - Add --skills option (default: True) consistent with Codex pattern - Update tests to inherit from SkillsIntegrationTests (28 tests pass) - Bump catalog entry to version 2.0.0 with updated description Assisted-by: IBM Bob (model: claude-sonnet-4-5, autonomous)
|
@mnriem please review, we need to make this work with new Bob... Thankyou so much |
There was a problem hiding this comment.
Pull request overview
This PR updates the built-in IBM Bob integration to align with Bob 2.0’s skills-based layout, switching installation output from command files to speckit-<name>/SKILL.md skills directories and bumping the integration’s catalog version accordingly.
Changes:
- Migrate
BobIntegrationfromMarkdownIntegrationtoSkillsIntegrationand update output paths to.bob/skills/.../SKILL.md. - Update Bob integration tests to use the shared
SkillsIntegrationTestsmixin. - Bump the Bob entry in
integrations/catalog.jsonto2.0.0with an updated description.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/integrations/bob/__init__.py |
Switch Bob to SkillsIntegration and update registrar/config output to .bob/skills + /SKILL.md. |
tests/integrations/test_integration_bob.py |
Update base test mixin and expected output directories for the skills layout. |
integrations/catalog.json |
Bump Bob integration version/description to reflect the 2.0.0 skills-based update. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 2
- Review effort level: Low
mnriem
left a comment
There was a problem hiding this comment.
As this fundamentally changes the layout for any Bob users what is the migration strategy? This will break them once they adopt a new version of Spec Kit so you need to make sure this goes through a deprecation cycle so they can migrate to the new Bob version. E.g make it an opt-in to the new version of Bob first and then in 2 minor releases (X.Y.Z where Y is minor) you can then remove the non-skill variant
Hi @mnriem |
|
Thanks @davidebibm — but I think we're talking about two different layers, and this still needs to change before it can land. Your point is about Bob the tool — that Bob 1.x can already read the skills layout. My concern is about Spec Kit's generated output: this PR changes what A hard cutover isn't acceptable here — we shouldn't catch existing users off guard. This needs to go through a proper deprecation cycle:
As it stands the Can you rework it along those lines — genuine dual-mode with skills opt-in first — so we phase this in without breaking anyone? |
|
Ok, thankyou @mnriem i'll do that |
|
@mnriem Done, hope this is what you are expecting |
|
Please address Copilot feedback. You will need to update the description to reflect the reality |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@mnriem Addressed Copilot comments and aligned with main |
|
Please address Copilot feedback and resolve conflicts |
…te legacy commands to opt-in
6b3a18c to
674a8db
Compare
…to ALWAYS_SLASH_AGENTS - init.py: suppress ai_skills=True when --legacy-commands is passed so extensions and presets target .bob/commands, not .bob/skills - _invocation_style.py: add 'bob' to ALWAYS_SLASH_AGENTS so init next-steps and hook invocations always show /speckit-<name> (skills is the default layout; no ai_skills flag required)
|
@mnriem Solved Copilot fb and rebased to avoid get Copilot feedback on other devs code 👍 |
…separators, extension-skill token resolution Addresses PR review 4716036212 (3 comments): 1. Bob legacy-install regression: `use`/`switch`/`upgrade` on an existing Bob 1.x project (only `.bob/commands/` on disk, no stored `legacy_commands`) called `is_skills_mode(None)` -> True and rewrote `ai_skills=True`, silently switching extension/command-reference handling to the skills layout. `is_skills_mode` now takes an optional `project_root`; Bob preserves an already-installed legacy layout until an explicit upgrade creates `.bob/skills/`. A fresh project still defaults to skills. 2. Copilot dual-mode separator: `invoke_separator_for_mode` was inherited from the base (mode-independent) and returned Copilot's static `.`, so preset/extension command refs in a Copilot skills project rendered `/speckit.<name>` instead of `/speckit-<name>`. Override it on Copilot to track the persisted `ai_skills` state, consistent with `build_command_invocation` and `effective_invoke_separator`. 3. Bob extension-skill command-ref tokens: verified that merging main's generic `_resolve_command_ref_tokens` (github#3544) resolves Bob's tokens via the `CONDITIONAL_SLASH_AGENTS` path (`/speckit-<name>`); added Bob to the command-ref regression parametrize plus dedicated Bob use-path tests. All tests pass (full suite green; merged with current main incl. github#3544). Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
|
Addressed the three review comments in 1. Bob legacy-install regression ( 2. Copilot dual-mode separator ( 3. Bob extension-skill command-ref tokens — with main merged, the generic Testing: full suite green on the merged result — 4524 passed, 5 skipped, 0 failures. Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously. |
…e shared-infra refresh (review github#3415) The `use`/`switch` paths refresh shared infrastructure via `_with_integration_setting()` / `_invoke_separator_for_integration()`, which previously resolved the invoke separator through `effective_invoke_separator` / `is_skills_mode` WITHOUT a project_root. For a pre-PR Bob 1.x project (.bob/commands/ on disk, no stored options), this defaulted to the skills "-" separator and rewrote rendered shared-template command refs to /speckit-*, even though ai_skills stayed false. Thread project_root through effective_invoke_separator, the two runtime helpers, and every call site so Bob's on-disk legacy detection governs the separator before shared infra is refreshed. Add a rendered-shared-template regression test covering `use --force`. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
|
Addressed review 4716253844 in Finding (valid): the legacy-layout detection wasn't applied when Fix: threaded Full suite green: 4526 passed, 5 skipped. Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously. |
…ng command-ref separator (review github#3415) `register_commands` runs once per detected agent, but the persisted `ai_skills` flag describes only the active integration (`opts["ai"]`). When another agent (e.g. Copilot) is active in skills mode while a legacy `.bob/commands` layout is also present, the previous code passed that global `True` to Bob's `invoke_separator_for_mode`, rewriting Bob 1.x command refs to `/speckit-*` instead of `/speckit.*`. Only consult the persisted flag for the agent it describes (`opts["ai"] == agent_name`); otherwise resolve the separator from the agent's own project-aware `effective_invoke_separator(None, project_root)`. Add regression tests covering the mismatched-active-agent case and a control for Bob-active skills mode. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
|
Addressed review 4716424313 in Finding (valid): Fix: only consult the persisted flag for the agent it describes ( Full suite green: 4528 passed, 5 skipped. Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously. |
…ls dir (review github#3415) Two related mis-detections from review 4723246468: 1. `BobIntegration.is_skills_mode` treated the mere presence of a `.bob/skills/` directory as proof the project is skills-based. A legacy Spec Kit install (managed `.bob/commands/speckit.*.md`) that also carried unrelated Bob 2 skills would be misclassified as skills, so `integration use bob` persisted `ai_skills` and rewrote shared refs. Now the layout is inferred from managed Spec Kit artifacts: legacy/command mode only when managed `speckit.*.md` command files exist and no managed `speckit-*` skill dirs do. 2. The `register_commands` separator for an inactive agent used a disk-based `effective_invoke_separator(None, project_root)` fallback that could pick the skills separator even though the registrar writes the static command layout (`.bob/commands/*.md`). Inactive agents now resolve the separator from the registrar's actual output layout (`extension == "/SKILL.md"`), so command-layout files keep `/speckit.*` refs regardless of sibling dirs. Update the affected hook/E2E tests to use managed artifacts and add regression tests for the mixed-layout and inactive-registrar scenarios. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
|
Addressed review 4723246468 in Comment 1 ( Comment 2 ( Updated the affected hook/E2E tests to use managed artifacts and added regression tests for the mixed-layout ( Full suite green: 4531 passed, 5 skipped. Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously. |
| **opts: Any, | ||
| ) -> list[Path]: | ||
| parsed_options = parsed_options or {} | ||
| if self.is_skills_mode(parsed_options): |
| registrar_config = { | ||
| "dir": ".bob/commands", | ||
| "format": "markdown", | ||
| "args": "$ARGUMENTS", | ||
| "extension": ".md", | ||
| } |
…ill post-processing (review github#3415) Two issues from review 4723782860: 1. `BobIntegration.setup()` resolved the layout via `is_skills_mode(parsed_options)` WITHOUT `project_root`, so `integration upgrade bob` on a Bob 1.x install (managed `.bob/commands/speckit.*.md`, no stored options) ignored the existing command files, generated skills, and stale-deleted the legacy commands — silently migrating the project. Pass `project_root` so the same managed-artifact detection used by `use` also governs upgrades. 2. Only `_BobSkillsHelper` overrode `post_process_skill_content` to suppress the shared slash-command hook note. Preset/extension skill generators call that hook on the registered `BobIntegration`, which inherited `IntegrationBase`'s note-injecting default. Repeat the no-op (delegating to the skills helper) on the registered class so every Bob skill-generation path is consistent with intent-activated core Bob skills. Add regression tests for the upgrade-preservation and post-processing paths. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
|
Addressed review 4723782860 in Comment 1 ( Comment 2 (skill post-processing inconsistency) — valid. Only Added regression tests for both (upgrade preservation + post-processing no-op). Full suite green: 4536 passed, 5 skipped. Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously. |
| if project_root is not None: | ||
| bob_dir = Path(project_root) / ".bob" | ||
| has_managed_skills = any((bob_dir / "skills").glob("speckit-*")) | ||
| has_managed_commands = any((bob_dir / "commands").glob("speckit.*.md")) | ||
| if has_managed_commands and not has_managed_skills: | ||
| return False |
| if _opts.get("ai") == agent_name: | ||
| _sep = _integ.invoke_separator_for_mode( | ||
| is_ai_skills_enabled(_opts) | ||
| ) |
| "version": "2.0.0", | ||
| "description": "IBM Bob 2.0 IDE skills-based integration", | ||
| "author": "spec-kit-core", | ||
| "repository": "https://github.com/github/spec-kit", | ||
| "tags": ["ide", "ibm"] | ||
| "tags": ["ide", "ibm", "skills"] |
…-review-bob-skills-pr-3415 # Conflicts: # tests/test_workflows.py
…ss (review github#3415) Address review github#3415 (4724160183): - Comment 1: Add an explicit `--skills` opt-in to BobIntegration. It forces the skills layout over on-disk auto-detection, giving legacy Bob 1.x installs a supported migration path (`integration upgrade bob --integration-options="--skills"`). `--skills` and `--legacy-commands` are mutually exclusive (clean exit-1 error). - Comment 2: In CommandRegistrar.register_commands, derive the command-ref separator from the output layout (agent_config["extension"]) for the active agent too, not the persisted ai_skills flag. A command-layout file (.bob/commands/*.md, .github/agents/*.agent.md) always renders /speckit.*; only a /SKILL.md scaffold uses /speckit-*. Dual-layout agents (Bob, Copilot) write skills via their own setup()/skills path, so register_commands only ever emits their command-layout files. - Comment 3: Update docs/reference/integrations.md Bob entry to document the skills-based default (.bob/skills/), the deprecated --legacy-commands opt-out, and the --skills migration path. Also fix a latent manifest-loss bug surfaced by the migration path: the upgrade Phase 2 stale-file cleanup built a throwaway manifest sharing the integration key and called uninstall(), which always deleted {key}.manifest.json. Any layout-shrinking upgrade (e.g. legacy->skills) thus wiped the freshly-saved manifest, leaving the project untracked and un-upgradeable. uninstall() now takes remove_manifest (default True); the stale-cleanup pass passes False. Adds regression tests for the --skills opt-in, mutual exclusion, corrected active-agent separator, remove_manifest=False, and an end-to-end legacy->skills migration that verifies the manifest survives and the project remains upgradeable. Full suite: 4555 passed, 5 skipped. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
|
Addressed review 4724160183 and resolved the merge conflict with Comment 1 — no migration path from legacy → skills. Added an explicit Comment 2 — active-agent separator ignored the output layout. Comment 3 — docs. Updated the Bob entry in While validating the migration end-to-end I found a latent bug it surfaces: the upgrade Phase 2 stale-file cleanup built a throwaway manifest sharing the integration key and called Added regression tests for each of the above (opt-in, mutual exclusion, corrected active-agent separator, Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously. |
Bob 2.0 replaces the command-based workflow with a skills-based layout.
https://bob.ibm.com/blog/bob-v2-release-announcement
Description
Testing
uv run specify --helpuv sync && uv run pytestAI Disclosure
Very simple code generated by Bob but verified by me